/*  
 * 极简AES加解密算法 （密钥字典加解密）
 * Version 1.1 Copyright (C) Qiepro kidming 2022-5-26.  
 * 
 * 密钥字符为不重复的任意字符
 * 加密后的数据会根据字典长度变化。字典长度最小为2，最大为128，最优为16，例：0123456789abcdef
 * 字典内容请不要以顺序排列，相当于密钥。如果要完全保证数据安全，字典数据不要存程序内部（可由输入数据传入参数）
 */
const default_key = '0123456789abcdefghijklmnopqrstuvwxyz';

/*  
 * @name 解密
 * @param {string} crypt_str 待解密的字符串
 * @param {string} aes_key 解密秘钥 （可不传）
 * @description 加密后的数据会根据字典长度变化。字典长度最小为2，最大为128，最优为16，
 * @description 字典内容请不要以顺序排列，相当于密钥。如果要完全保证数据安全，字典数据不要存程序内部（可由输入数据传入参数）
 */
export function Decrypt(crypt_str: string, aes_key?: string):string {
	aes_key = StrUnique(aes_key == null ? default_key : String(aes_key));
	if (aes_key.length < 2) throw new Error('最小长度为2');
	let max = 255; // 最大值
	let alen; // 加密过后单字符长度
	for (alen = 0; max > 0; alen++) max = Math.floor(max / aes_key.length); //计算单字符加密后长度
	let result:string[] = [];
	let code = 0;
	for (let i = crypt_str.length - 1; i >= 0; i--) {
		code += aes_key.indexOf(crypt_str.charAt(i)) * (aes_key.length ** ((alen - 1) - (i % alen)))
		if (i % alen === 0) {
			result.unshift(String.fromCharCode(code + ((crypt_str.length / alen) % 13)))
			code = 0;
		}
	}
	return decodeURIComponent(result.join(''));
}
/*  
 * @name 加密
 * @param {string} source_str 待加密的字符串
 * @param {string} aes_key 解密秘钥 （可不传）
 * @description 加密后的数据会根据字典长度变化。字典长度最小为2，最大为128，最优为16，
 * @description 字典内容请不要以顺序排列，相当于密钥。如果要完全保证数据安全，字典数据不要存程序内部（可由输入数据传入参数）
 */
export function Encrypt(source_str: string, aes_key?: string):string {
	aes_key = StrUnique(aes_key == null ? default_key : String(aes_key));
	source_str = encodeURIComponent(source_str);
	if (aes_key.length < 2) throw new Error('最小长度为2');
	let max = 255; // 最大值
	let alen; // 加密过后单字符长度
	for (alen = 0; max > 0; alen++) max = Math.floor(max / aes_key.length); //计算单字符加密后长度
	let result = '';
	for (let i = 0; i < source_str.length; i++) {
		let num = source_str.charCodeAt(i) - (source_str.length % 13) // 字符编码，用fromCharCode解码；
		let arr = new Array(alen); // 单字符转换过后的数组
		for (let si = alen; si > 0; si--) {
			arr[si - 1] = aes_key.charAt(num % aes_key.length)
			num = Math.floor(num / aes_key.length);
		}
		result += arr.join('');
	}
	return result;
}

 function StrUnique(str: string): string {
	let temp = str.split('');
	const resArr = Array.from(new Set(temp));
	return resArr.join('');
};